#include <iostream>
#include <sstream>
#include <fstream>

#include "parser.h"
#include "unary_parser.h"
using namespace eg;
using namespace std;

class eg_parser_test: public parser {

public:

	eg_parser_test();
	~eg_parser_test() {
	}

	bool parse(bool gen_ast) {
		return g.parse();
	}

	string to_string();

private:

	rule g, g1 ,ag, expr, term, factor, number,err;

};

eg_parser_test::eg_parser_test() :
	g("set_of_grammars"),g1 ("grammars"), ag("a_grammar"), expr("expr"), term("term"), factor("fact"),
			number("num"), err ("error") {
	//g = g1 + a_char('#');
	//g1 = (ag|err )+(ag|err )+ (ag|err )+(ag|err ) +(ag|err )+(ag|err );
	g =   one_or_more(ag |err) + a_char('#') ;
	err = error('\n', '#');
	ag = (expr + a_char('\n'));						// g      = expr '#'
	expr = term + maybe(a_char('+') + term ); // expr   = term ('+' term)?
	term = factor + maybe(a_char('*') + factor); // term   = factor ('*' factor)?
	factor = number | (a_char('(') + expr + a_char(')'));// factor = number /'(' expr ')'
	number = maybe(a_char('-')) + one_or_more(in("0123456789")); // number = '-'? [0123456789]+
}

string eg_parser_test::to_string() {
	string s;
	s += g.to_string() + '\n';
	s += g1.to_string() + '\n';
	s += ag.to_string() + '\n';
	s += expr.to_string() + '\n';
	s += term.to_string() + '\n';
	s += factor.to_string() + '\n';
	s += number.to_string()+ '\n';
	s += err.to_string();
	return s;
}

 int main() {
	std::stringstream in;
	eg_parser_test p;
	blanks * b = new blanks;

	std::fstream file;
	file.open("prueba.txt", fstream::in);

	if (file) {
		in << file.rdbuf();
		file.close();
	}

	istringstream in2("1    +1;#");

	cout << "Grammar listing:\n";
	cout << "----------------------------------------\n";
	if (not p.is_left_recursive())
		cout << p.to_string() << endl;
	cout << "----------------------------------------\n" << endl;
	ast *t = p.do_parsing(in, b);
	cout << "done...\n";
	if (t) {
		cout << "Sucess.\n" << "Syntax tree: " << t->to_string() << endl;
		//cout << "new line cant " << t->get_new_line() << endl;
	} else
		cout << "Failed" << endl;

}
